package com.inspectortime.webapp;

import java.text.DateFormat;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.inspectortime.domain.Inspection;
import com.inspectortime.domain.billing.Payment;
import com.inspectortime.domain.billing.PaymentMethod;
import com.inspectortime.domain.billing.PaymentSourceType;
import com.inspectortime.repository.Factory;
import com.inspectortime.repository.Repository;
import com.inspectortime.webapp.payment.AbstractPaymentRequestHelper;
import com.inspectortime.webapp.payment.AuthorizeNetPaymentRequestHelper;
import com.inspectortime.webapp.payment.PayPalPaymentRequestHelper;
import com.inspectortime.webapp.payment.PaymentUtils;
import com.inspectortime.webapp.util.HttpSessionUtils;
import com.inspectortime.webapp.util.RequestPathUtils;

public class InspectionSchedulingConfirmationController implements Controller {

	private static Log log = LogFactory
			.getLog(InspectionSchedulingConfirmationController.class);

	private Repository repository;
	private Factory factory;
	private boolean paymentTestMode;
	private String formView;

	public void setPaymentTestMode(boolean paymentTestMode) {
		this.paymentTestMode = paymentTestMode;
	}

	public void setFactory(Factory factory) {
		this.factory = factory;
	}

	public void setFormView(String s) {
		formView = s;
	}

	public ModelAndView handleRequest(HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		Inspection inspection = HttpSessionUtils.retrieveWizardInspection(
				request, repository);

		ModelAndView mv = new ModelAndView(formView);
		mv.addObject("inspection", inspection);

		// Prepare variables that may be used by both paypal and authorize.net
		String[] invoiceUniqueFields = PaymentUtils.generateInvoiceNumber();
		int timestamp = Integer.parseInt(invoiceUniqueFields[0]);
		int sequenceNumber = Integer.parseInt(invoiceUniqueFields[1]);
		String invoiceNumber = invoiceUniqueFields[2];
		String description = "Inspection at "
				+ inspection.getProperty().getLocation().getStreet1() + " in " + inspection.getProperty().getLocation().getCity()
				+ " on "
				+ DateFormat.getDateInstance(DateFormat.LONG).format(
						inspection.getInspectionTime()) + " by "
				+ inspection.getInspector().getCompany().getName();

		// Prepare form for a Authorize.net SIM payment submission
		AuthorizeNetPaymentRequestHelper paymentRequest = null;
		if (StringUtils.hasText(inspection.getInspector().getCompany()
				.getSimLoginId())) {
			paymentRequest = new AuthorizeNetPaymentRequestHelper(inspection
					.getInspector().getCompany().getSimLoginId(), inspection
					.getInspector().getCompany().getSimTransactionKey());
			paymentRequest.setInvoiceNumber(invoiceNumber);
			paymentRequest.setSequenceNumber(sequenceNumber);
			paymentRequest.setTimestamp(timestamp);
			paymentRequest.setAmount(String.valueOf(inspection
					.getInspectionFee()));
			paymentRequest.setDescription(description);
			paymentRequest.generateFingerprint();
			paymentRequest.setTestMode(paymentTestMode);
			mv.addObject("authorizeNetPaymentRequest", paymentRequest);
		}

		// Prepare for paypal
		PayPalPaymentRequestHelper paypalRequest = null;
		if (inspection.getInspector().getCompany().isPaypalEnabled()) {
			paypalRequest = new PayPalPaymentRequestHelper();
			paypalRequest.setInvoiceNumber(invoiceNumber);
			paypalRequest.setSequenceNumber(sequenceNumber);
			paypalRequest.setTimestamp(timestamp);
			paypalRequest.setPaymentEmail(inspection.getInspector()
					.getCompany().getPaypalPaymentEmail());
			String contextPath = RequestPathUtils.extractWebappUrl(request);
			paypalRequest.setNotifyUrl(contextPath
					+ "/payment/paypal/confirmation.html");
			if (paymentTestMode) {

				// Paypal does not support a test mode per se, but we make the
				// transaction amount very small instead
				paypalRequest.setAmount("0.01");
			} else {
				paypalRequest.setAmount(String.valueOf(inspection
						.getInspectionFee()));
			}
			paypalRequest.setDescription(description);
			paypalRequest.setTestMode(paymentTestMode);
			mv.addObject("paypalPaymentRequest", paypalRequest);
		}

		// This is dumb but we populate Payment from either of the two helper
		// classes. At some point the PaymentRequest class hierarchy should be
		// revisited to make this more intuitive
		AbstractPaymentRequestHelper abstractRequest = null;
		if (paymentRequest != null) {
			abstractRequest = paymentRequest;
		} else if (paypalRequest != null) {
			abstractRequest = paypalRequest;
		}

		if (abstractRequest != null) {

			// Create a payment record in the database which we'll use to look
			// up
			// this transaction during the call-back POST request coming from
			// either Authorize.net or PayPal. Note that incomplete records will
			// probably need to be
			// purged at some point.
			Payment payment = factory
					.createPayment(PaymentSourceType.INSPECTION);
			payment.setPaymentInvoiceNumber(paymentRequest.getInvoiceNumber());
			payment.setDescription(paymentRequest.getDescription());
			payment.addPaymentLineItem((String) inspection.getId());
			payment.setAmount(inspection.getInspectionFee());
			payment.save();
		}

		return mv;
	}

	public void setRepository(Repository repository) {
		this.repository = repository;
	}

}
